<?php
/**
 * @license http://www.gnu.org/licenses/gpl.html GNU GPL, version 3 or later
 * @package FrontPress
 * @subpackage Route
 */

/**
 * Semi-persistent notice system.
 *
 * The notices are sent to the user in the form of a session cookie, which is
 * deleted as soon as the notices are shown.
 *
 * <b>For template designers:</b>
 *
 * Templates should implement styling for at least three notice types:
 * <ul>
 * <li>notice (the default) - It is suggested that this is a neutral color and
 * that the style is also used for unknown notice types. CSS selector: .notice</li>
 * <li>error - Should have a red tint. CSS selector: .notice-error</li>
 * <li>success - Should have a green tint. CSS selector: .notice-success</li>
 * </ul>
 *
 * Try to keep the different notice styles relatively similar to each other. The
 * notices should be shown above the page content, preferably below the header.
 *
 * @since 2010-07-30-r36
 * @version $Id: class.fp-notice.php 37 2010-07-30 22:10:44Z Nightgunner5 $
 */
class FP_Notice {
	private static $notices = array();
	static $allowedtags;
	private static $prefix;

	/**
	 * Private constructor to prevent initialization.
	 */
	private function __construct() {
	}

	/**
	 * Get the notices that haven't been shown yet ready to be shown.
	 */
	private static function _init() {
		if ( !static::$prefix ) {
			static::$prefix = md5( frontpress_uri() );
			static::$allowedtags = apply_filters( 'fp_notice_allowed_tags',  array(
				'a' => array(
					'href' => array(),
					'title' => array()),
				'abbr' => array(
					'title' => array()),
				'acronym' => array(
					'title' => array()),
				'b' => array(),
				'blockquote' => array(
					'cite' => array()),
				'br' => array(),
				'cite' => array (),
				'code' => array(),
				'del' => array(
					'datetime' => array ()),
				'dd' => array(),
				'dl' => array(),
				'dt' => array(),
				'em' => array (), 'i' => array (),
				'ins' => array('datetime' => array(), 'cite' => array()),
				'li' => array(),
				'ol' => array(),
				'p' => array(),
				'q' => array(
					'cite' => array()),
				'strike' => array(),
				'strong' => array(),
				'sub' => array(),
				'sup' => array(),
				'u' => array(),
				'ul' => array(),
			) );
			foreach ( $_COOKIE as $key => $_val ) {
				if ( preg_match( '/^' . static::$prefix . '_fp_notice_(.+)$/', $key, $type ) ) {
					if ( is_serialized( $_val ) && is_array( $val = unserialize( $_val ) ) ) {
						foreach ( $val as $notice ) {
							static::_add( $notice, $type[1] );
						}
					}
				}
			}
			do_action( 'fp_notice_init' );
		}
	}

	/**
	 * Add a notice. If the notices are not shown on the page after this
	 * is called, a cookie will be set and the notice will be shown as soon
	 * as {@link FP_Notice::print_notices()} is called.
	 *
	 * @param string $text The text of the notice. This will be run through KSES and autop.
	 * @param string $type Optional. The type of notice being issued. Standard types are
	 *                     notice (default), error, and success.
	 */
	static function add( $text, $type = 'notice' ) {
		static::_init();
		static::_add( $text, $type );
		$fpuri = parse_url( frontpress_uri() );
		backpress_set_cookie( static::$prefix . '_fp_notice_' . $type, serialize( static::$notices[$type] ),
			0, $fpuri['path'], $fpuri['domain'], false, true );
	}

	/**
	 * Add a notice to the cache.
	 *
	 * @param string $text The text of the notice. This will be run through KSES and autop.
	 * @param string $type Optional. The type of notice being issued. Standard types are
	 *                     notice (default), error, and success.
	 */
	static private function _add( $text, $type = 'notice' ) {
		static::$notices[$type][] = wpautop( force_balance_tags( wp_kses( $text, static::$allowedtags ) ) );
	}

	/**
	 * Write some or all waiting notices to the page.
	 *
	 * @param string $type Optional. Use this to limit the type of notices that will be
	 *                     shown. If this is null, all notices will be shown.
	 */
	static function print_notices( $type = null ) {
		static::_init();
		if ( is_null( $type ) ) {
			foreach ( array_keys( static::$notices ) as $type ) {
				static::print_notices( $type );
			}
		} else {
			foreach ( (array) static::$notices[$type] as $notice ) {
				echo apply_filters( 'fp_notice_print', '<div class="notice notice-' . $type . '">' . $notice . '</div>', $notice, $type );
			}
			unset( static::$notices[$type] );
			$fpuri = parse_url( frontpress_uri() );
			backpress_set_cookie( static::$prefix . '_fp_notice_' . $type, '',
				-1, $fpuri['path'], $fpuri['domain'], false, true );
		}
	}
}

// This is required so that FP_Notice::add() and FP_Notice::print_notices()
// can be called after data is outputted to the client.
ob_start();